import { MyMath } from "../../../core/utils";

//@ts-ignore
const gfx = cc.gfx;
const QuadBuffer = cc["QuadBuffer"];
const MeshBuffer = cc["MeshBuffer"];
const InputAssembler = cc.renderer["InputAssembler"];

var vfmtCustom = new gfx.VertexFormat([
    { name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },   //xy
    { name: gfx.ATTR_UV0, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },        // texture纹理uv
    { name: gfx.ATTR_COLOR, type: gfx.ATTR_TYPE_UINT8, num: 4, normalize: true },  // 4 * uint == 1 float32
]);

const vfmt_XY_UV_COLOR = gfx.VertexFormat.XY_UV_Color;
const FLOATS_PER_VERT = 5;
const COLOR_OFFSET = 4;

const FLOAT_PER_PARTICLE = 4 * FLOATS_PER_VERT;

const COLOR_WHITE_VAL = cc.Color.WHITE["val"];

export default class BulletParticleSystemAssembler extends cc.Assembler {
    _buffer: any = null;
    _ia: any = null;
    _vfmt: any = null;
    _uvFilled = 0;

    init(comp) {
        this._buffer = null;
        this._ia = null;
        this._vfmt = vfmt_XY_UV_COLOR;
    }

    getBuffer() {
        if (!this._buffer) {
            // Create quad buffer for vertex and index
            this._buffer = new QuadBuffer(cc.renderer["_handle"], vfmt_XY_UV_COLOR);

            this._ia = new InputAssembler();
            this._ia._vertexBuffer = this._buffer._vb;
            this._ia._indexBuffer = this._buffer._ib;
            this._ia._start = 0;
            this._ia._count = 0;
        }
        return this._buffer;
    }

    fillBuffers(comp, renderer) {
        if (!this._ia) return;

        const PositionType = cc.ParticleSystem.PositionType;
        if (comp.positionType === PositionType.RELATIVE) {
            renderer.node = comp.node.parent;
        } else {
            renderer.node = comp.node;
        }
        renderer.material = comp._materials[0];
        renderer._flushIA(this._ia);
    }

    update(comp, dt) {
        if (CC_EDITOR && !comp.preview) return;
        let particleCount = comp.particleLife.length;

        let buffer = this.getBuffer();
        buffer.reset();
        buffer.request(particleCount * 4, particleCount * 6);

        if (particleCount > this._uvFilled) {
            this.updateUVs(comp);
        }
        let particleIdx = 0;
        for (let i = 0; i < comp.particleLife.length; i++) {
            let offset = FLOAT_PER_PARTICLE * particleIdx;
            if (comp.particleLife[i] > 0) {
                //制造颜色
                // let color = cc.color();
                let pc = comp.particleLife[i] / comp.particleLifeMax[i];
                let color = (<cc.Color>comp.color2).lerp(comp.color1, pc);
                let size = MyMath.Lerp(comp.size1, comp.size2, pc);
                this.updateParticleBuffer(comp.particleX[i], comp.particleY[i], size, buffer, offset, color["_val"]);
            }
            particleIdx++;
        }

        this._ia._count = particleCount * 6;
        if (particleCount > 0) {
            buffer.uploadData();
        }
    }
    updateParticleBuffer(x, y, size, buffer, offset, color) {
        let vbuf = buffer._vData;
        let uintbuf = buffer._uintVData;

        let width = size;
        let height = width;
        let halfWidth = width / 2;
        let halfHeight = height / 2;
        // pos
        // bl
        vbuf[offset] = x - halfWidth;
        vbuf[offset + 1] = y - halfHeight;
        uintbuf[offset + COLOR_OFFSET] = color;
        offset += FLOATS_PER_VERT;
        // br
        vbuf[offset] = x + halfWidth;
        vbuf[offset + 1] = y - halfHeight;
        uintbuf[offset + COLOR_OFFSET] = color;
        offset += FLOATS_PER_VERT;
        // tl
        vbuf[offset] = x - halfWidth;
        vbuf[offset + 1] = y + halfHeight;
        uintbuf[offset + COLOR_OFFSET] = color;
        offset += FLOATS_PER_VERT;
        // tr
        vbuf[offset] = x + halfWidth;
        vbuf[offset + 1] = y + halfHeight;
        uintbuf[offset + COLOR_OFFSET] = color;
    }
    protected updateUVs(comp, force = false) {
        let buffer = this.getBuffer();
        let vbuf = buffer._vData;

        let start = force ? 0 : this._uvFilled;
        let particleCount = comp.particleLife.length;
        for (let i = start; i < particleCount; i++) {
            let offset = i * FLOAT_PER_PARTICLE;
            vbuf[offset + 2] = QuadUvMapping[0];
            vbuf[offset + 3] = QuadUvMapping[1];
            offset += FLOATS_PER_VERT;
            vbuf[offset + 2] = QuadUvMapping[2];
            vbuf[offset + 3] = QuadUvMapping[3];
            offset += FLOATS_PER_VERT;
            vbuf[offset + 2] = QuadUvMapping[4];
            vbuf[offset + 3] = QuadUvMapping[5];
            offset += FLOATS_PER_VERT;
            vbuf[offset + 2] = QuadUvMapping[6];
            vbuf[offset + 3] = QuadUvMapping[7];
        }
        this._uvFilled = particleCount;
    }
}

const QuadUvMapping = [
    0, 1,// 1 left bottom
    1, 1,// 2 right bottom
    0, 0,// 0 left top
    1, 0,// 3 right top
];